package org.example.utils;

import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class OkHttp3Utils {
    private static OkHttpClient okHttpClient = null;

    public static final int OKHTTP_CONNECT_TIME = 5;

    public static final int OKHTTP_READ_TIME = 20;

    public static final int OKHTTP_WRITE_TIME = 20;

    public static final String UTF8 = "utf-8";

    public static final Logger log = LoggerFactory.getLogger(OkHttp3Utils.class);
    public static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");
    public static final MediaType CONTENT_TYPE_TEXT = MediaType.parse("application/text-html;charset=utf-8");
    public static final MediaType FORM = MediaType.parse("application/x-www-form-urlencoded;charset=utf-8");

    private OkHttp3Utils() {
    }

    static {
        if (okHttpClient == null) {
            //加同步安全
            synchronized (OkHttp3Utils.class) {
                if (okHttpClient == null) {
                    //构建器
                    okHttpClient = new OkHttpClient.Builder()
                            //连接超时
                            .connectTimeout(OKHTTP_CONNECT_TIME, TimeUnit.SECONDS)
                            //写入超时
                            .writeTimeout(OKHTTP_WRITE_TIME, TimeUnit.SECONDS)
                            //读取超时
                            .readTimeout(OKHTTP_READ_TIME, TimeUnit.SECONDS)
                            .build();
                }
            }
        }
    }

    /**
     * get请求
     * 参数1 url
     * 参数2 回调Callback
     */

    public static void doGet(String url, Callback callback) {
        //创建Request
        Request request = new Request.Builder().url(url).build();
        //得到Call对象
        Call call = okHttpClient.newCall(request);
        //执行异步请求
        call.enqueue(callback);


    }

    /**
     * post请求
     * 参数1 url
     * 参数2 Map<String, String> params post请求的时候给服务器传的数据
     * add..("","")
     * add()
     */

    public static void doPost(String url, Map<String, String> params, Callback callback) {

        //3.x版本post请求换成FormBody 封装键值对参数

        FormBody.Builder builder = new FormBody.Builder();
        //遍历集合
        for (String key : params.keySet()) {
            builder.add(key, params.get(key));

        }


        //创建Request
        Request request = new Request.Builder().url(url).post(builder.build()).build();

        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);

    }

    /**
     * post请求上传文件....包括图片....流的形式传任意文件...
     * 参数1 url
     * file表示上传的文件
     * fileName....文件的名字,,例如aaa.jpg
     * params ....传递除了file文件 其他的参数放到map集合
     */
    public static String uploadFile(String url, File file, String fileName, Map<String, String> params) throws IOException {

        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);

        //参数
        if (params != null) {
            for (String key : params.keySet()) {
                builder.addFormDataPart(key, params.get(key));
            }
        }
        //文件...参数name指的是请求路径中所接受的参数...如果路径接收参数键值是fileeeee,此处应该改变
        builder.addFormDataPart("media", fileName, RequestBody.create(MediaType.parse("application/octet-stream"), file));

        //构建
        MultipartBody multipartBody = builder.build();

        //创建Request
        Request request = new Request.Builder().url(url).post(multipartBody).build();

        log.info("Post文件上传请求URL:{},参数:{}", url, JSONObject.toJSONString(params));

        //得到Call
        Response execute = okHttpClient.newCall(request).execute();

        String s = execute.body().string();
        log.info("result:{}", s);

        return s;
/*        //执行异步请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //上传成功回调 目前不需要处理
                if (response.isSuccessful()){
                    String s = response.body().string();
                    System.out.println("result:{}",s);
                }
            }
        });*/

    }

    /**
     * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"}
     * 参数一：请求Url
     * 参数二：请求的JSON
     * 参数三：请求回调
     */
    public static void doPostJson(String url, String jsonParams, Callback callback) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);
        Request request = new Request.Builder().url(url).post(requestBody).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);

    }


    public static String tryGet(String url, int maxTry) {
        if (maxTry < 0) {
            maxTry = 1;
        }
        IOException ex = null;
        for (int i = 0; i < maxTry; i++) {
            try {
                return get(url);
            } catch (IOException e) {
                ex = e;
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }
        log.error("Http get 请求异常,url={},tryTimes={}", url, maxTry, ex);
        return null;
    }

    public static String get(String url, Map<String, Object> params) throws IOException {
        return get(url, params, null);
    }

    public static byte[] get2(String url) throws IOException {
        return _get2(url);
    }

    public static String get(String url, Map<String, Object> params, Map<String, String> headers) throws IOException {
        StringBuilder sb = new StringBuilder(url);
        sb.append("?");
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String value = "";
            try {
                value = URLEncoder.encode(entry.getValue().toString(), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                log.error("编码转换失败,{}", entry.getValue());
            }
            sb.append(entry.getKey()).append("=").append(value).append("&");
        }
        return _get(sb.toString(), headers);
    }


    public static String get(String url) throws IOException {
        return _get(url, null);
    }

    private static String _get(String url, Map<String, String> headers) throws IOException {
        Request.Builder builder = new Request.Builder().url(url);
        if (MapUtils.isNotEmpty(headers)) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }

        Request request = builder.build();
        long start = System.currentTimeMillis();
        Response response = okHttpClient.newCall(request).execute();
        long end = System.currentTimeMillis();
        String res = response.body().string();
        log.info("{},接口耗时:{}ms,{}", url, end - start, res);
        return res;
    }

    private static byte[] _get2(String url) throws IOException {
        Request.Builder builder = new Request.Builder().url(url);
        Request request = builder.build();
        long start = System.currentTimeMillis();
        Response response = okHttpClient.newCall(request).execute();
        long end = System.currentTimeMillis();
        byte[] res = response.body().bytes();
        log.info("{},接口耗时:{}ms", url, end - start);
        return res;
    }


    public static byte[] post2(String url, String json) throws IOException {
        RequestBody body = RequestBody.create(JSON, json);
        log.info("Post请求URL:{},参数:{}", url, JSONObject.toJSONString(json));
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        long start = System.currentTimeMillis();
        Response response = okHttpClient.newCall(request).execute();
        long end = System.currentTimeMillis();
        byte[] res = response.body().bytes();
        log.info("{},接口耗时:{}ms", url, end - start);
        return res;
    }

    public static String post(String url, String json) throws IOException {
        RequestBody body = RequestBody.create(JSON, json);
        log.info("Post请求URL:{},参数:{}", url, JSONObject.toJSONString(json));
        return _post(url, body);
    }

    public static String post(String url, byte[] data) throws IOException {
        RequestBody body = RequestBody.create(JSON, data);
        return _post(url, body);
    }


    public static byte[] post2(String url, byte[] data) throws IOException {
        RequestBody body = RequestBody.create(JSON, data);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = okHttpClient.newCall(request).execute();
        return response.body().bytes();

    }

    public static String postForm(String url, Map<String, String> paramMap) throws IOException {
        FormBody.Builder builder = new FormBody.Builder();
        if (MapUtils.isNotEmpty(paramMap)) {
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }
        log.info("Post请求URL:{},参数:{}", url, JSONObject.toJSONString(paramMap));
        return _post(url, builder.build());
    }

    public static String _post(String url, RequestBody body) throws IOException {
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        long start = System.currentTimeMillis();
        Response response = okHttpClient.newCall(request).execute();
        long end = System.currentTimeMillis();
        String res = response.body().string();
        log.info("{},接口耗时:{}ms,resp:{}", url, end - start, res);
        return res;
    }


    public static InputStream _postZip(String url, RequestBody body) throws IOException {

        Request request = new Request.Builder()
                .addHeader("Content-Encoding", "gzip")
                .url(url)
                .post(body)
                .build();
        long start = System.currentTimeMillis();
        Response response = okHttpClient.newCall(request).execute();
        long end = System.currentTimeMillis();
        InputStream in = response.body().byteStream();
        log.info("{},接口耗时:{}ms", url, end - start);
        return in;
    }

    public static String _post(String url, RequestBody body, Map<String, String> headers) throws IOException {

        Request.Builder builder = new Request.Builder().url(url);
        if (MapUtils.isNotEmpty(headers)) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        Request request = builder.post(body).build();
        long start = System.currentTimeMillis();
        Response response = okHttpClient.newCall(request).execute();
        long end = System.currentTimeMillis();
        String res = response.body().string();
        log.info("{},接口耗时:{}ms,resp:{}", url, end - start, res);
        return res;
    }

}

